#include "../StdInc.h"

#ifndef _RUN_COMMANDLINE_MODE


namespace GSTrader
{
	namespace QuoteService
	{
		CDataManager::CDataManager(CFrameworkBase* pFrameWork) : m_uUnusedBarSeriesNum(20)
		{
			m_pFramework = pFrameWork;
			m_pDataBase = (CDataBaseProxy*)pFrameWork->GetDataBasePtr();

			m_strRootPath = "data/";
			bool bOk = CFileSystem::CreateCurrentSubDir(m_strRootPath);
			for (uint32 x = 0; x < m_uUnusedBarSeriesNum; x++)
			{
				m_listUnusedBarSeries.push_back(new CBarSeries);
			}
			m_uQuoteSequence = NULL;
			m_pRealQuoteManager = new CRealQuoteManager(this);
			m_pHistoricalDataManager = new CHistoricalDataManager(this);

			m_pDataQueue = new CMsgQueue;
			m_pFramework->AddDataMsgQueue(m_pDataQueue);

			m_pThread = new thread(bind(&CDataManager::TimeThread, this));

		}

		CDataManager::~CDataManager()
		{
			m_pThreadRunStatus = trsStop;
			while (m_pThread && m_pThreadRunStatus != trsExit && ThreadSleep(200));
			_delete_thread(m_pThread);

			m_pFramework->DeleteDataMsgQueye(m_pDataQueue);
			_delete(m_pDataQueue);

			_delete(m_pHistoricalDataManager);
			_delete(m_pRealQuoteManager);

			for (unordered_map<CBarSeries*, uint32>::iterator it = m_mapRegisterBarSeries.begin(); it != m_mapRegisterBarSeries.end(); it++)
			{
				delete it->first;
			}

			for (list<CBarSeries*>::iterator it = m_listUnusedBarSeries.begin(); it != m_listUnusedBarSeries.end(); it++)
			{
				delete(*it);
			}
		}

		void CDataManager::CreateServerQuoteApi()
		{

		}

		CDepthMarketData* CDataManager::OnMarketData(CDepthMarketData* pMarketData)
		{
			if (pMarketData == nullptr || pMarketData->m_nInstrumentID < 0)
			{
				assert(false);
				return nullptr;
			}
			unique_lock<mutex> Lock(m_QuoteMutex);
			m_pRealQuoteManager->OnMarketData(pMarketData);
			m_uQuoteSequence++;
			return pMarketData;
		}

		void CDataManager::TimeThread()
		{

		}

		bool CDataManager::GetHistoricalData(CBarSeriesIndex& BarSeriesIndex, vector<SHistoricalData>& vResultHistoricalData)
		{
			assert(vResultHistoricalData.empty());
			EDataCycle eDataCycle = BarSeriesIndex.m_eDataCycle;
			EDataCycle eRawDataCycle = BarSeriesIndex.GetRawDataCycle();
			vector<SHistoricalData> vRealData, vHistoricalData;
			bool bRealDataOk = false;
			if (eDataCycle == dcReal ||	eRawDataCycle <= dcSec1)
			{
				return m_pRealQuoteManager->GetHistoricalData(BarSeriesIndex, vResultHistoricalData);
			}
			else
			{
				bRealDataOk = m_pRealQuoteManager->GetHistoricalData(BarSeriesIndex, vRealData);
			}
			bool bHisDataOk = m_pHistoricalDataManager->GetHistoricalData(BarSeriesIndex, vResultHistoricalData);
			if (!bHisDataOk && !bRealDataOk)
			{
				return false;
			}
			else if (bRealDataOk)
			{
				if (vResultHistoricalData.empty())
				{
					vResultHistoricalData = vRealData;
				}
				else if (vRealData.front().m_tTime > vResultHistoricalData.back().m_tTime)
				{
					vResultHistoricalData.insert(vResultHistoricalData.end(), vRealData.begin(), vRealData.end());
				}
			}
			this->ProcessMultiCycleData(BarSeriesIndex, vResultHistoricalData);
			return (!vResultHistoricalData.empty());
		}

		CBarSeries* CDataManager::GetUnusedBarSeries()
		{
			uint32 uNum = m_uUnusedBarSeriesNum / 3;
			if (m_listUnusedBarSeries.size() < uNum)
			{
				do
				{
					m_listUnusedBarSeries.push_back(new CBarSeries);
				}
				while (m_listUnusedBarSeries.size() < m_uUnusedBarSeriesNum);
			}

			CBarSeries* pBarSeries = m_listUnusedBarSeries.front();
			m_listUnusedBarSeries.pop_front();
			return pBarSeries;
		}

		CBarSeries* CDataManager::RegisterTimeBar(CBarSeriesIndex& BarSeriesIndex)
		{

			return NULL;
		}

		void CDataManager::UnRegisterTimeBar(CBarSeries* pBarSeries)
		{
			unique_lock<mutex> Lock(m_QuoteMutex);
			auto it = m_mapRegisterBarSeries.find(pBarSeries);
			if (it == m_mapRegisterBarSeries.end())
			{
				assert(false);
				return;
			}
			it->second--;
			if (it->second != 0)
			{
				return;
			}

			auto it2 = m_mapRegisterBarSeriesIndex.find(*pBarSeries);
			if (it2 != m_mapRegisterBarSeriesIndex.end() && it2->second == pBarSeries)
			{
				m_mapRegisterBarSeriesIndex.erase(it2);
			}

			m_mapRegisterBarSeries.erase(it);
			pBarSeries->Release();
			delete pBarSeries;
		}

		void CDataManager::ProcessMultiCycleData(CBarSeriesIndex& BarSeriesIndex, vector<SHistoricalData>& vHisData)
		{
	
		}

		void CDataManager::UniteMinMultiCycleData(uint32 uMultiCycle, vector<SHistoricalData>& vHisData)
		{
			if (uMultiCycle == 0 || vHisData.empty())
			{
				return;
			}

			uint32 uLoadNum = vHisData.size();
			SHistoricalData* pSrcData = &vHisData.front();
			SHistoricalData* pDestData = pSrcData;
			pDestData--;
			uint32 uNumData = 0;
			uint32 uCount = 0;
			while (uLoadNum--)
			{
				if (!uCount)
				{
					pDestData++;
					memcpy(pDestData, pSrcData, sizeof(SHistoricalData));
					uCount = uMultiCycle;
					uNumData++;
				}
				else
				{
					UniteHisData(pSrcData, pDestData);
				}
				pSrcData++;
				uCount--;
			}
			vHisData.resize(uNumData);
		}

		void CDataManager::UniteHisData(const SHistoricalData* pSrcData, SHistoricalData* pDestData)
		{
			pDestData->m_tTime = pSrcData->m_tTime;
			if (pDestData->m_dHigh < pSrcData->m_dHigh)
			{
				pDestData->m_dHigh = pSrcData->m_dHigh;
			}

			if (pDestData->m_dLow > pSrcData->m_dLow)
			{
				pDestData->m_dLow = pSrcData->m_dLow;
			}

			pDestData->m_dClose = pSrcData->m_dClose;
			pDestData->m_dVolume += pSrcData->m_dVolume;
			pDestData->m_dAmount += pSrcData->m_dAmount;
			pDestData->m_dOpenInterest = pSrcData->m_dOpenInterest;
		}

		//////////////////////////////////////////////////////////////////////////
		void CDataManager::OnConnected(PVOID pApi)
		{
	
		}

		void CDataManager::ConnectQuoteServer(string strUserID, string m_strBrokerID)
		{
	
		}

		void CDataManager::DisconnectQuoteServer()
		{
	
		}

		void CDataManager::OnRtnTickData(string strExchangeId, string strCode, vector<SGSTickData>& vTickData)
		{
			
		}

		void CDataManager::OnRtnHistoricalData(string strExchangeId, string strCode, WORD wDataCycle, SHistoricalData* pHistoricalData, UINT uDataCount)
		{
	
		}

	

		void CDataManager::OnMainInstrument(vector<string>& vInstruent)
		{
			vector<string>* pvInstruent = new vector<string>;
			*pvInstruent = vInstruent;
			MakeMsgCarryPtr(msgOnMainInstrument, pvInstruent);
			m_pDataQueue->Push(pMsg);
		}
	}
}

#endif